//LightHelper.h
//Created 26/08/13
//Created By Daniel Bowler
//
//This header will include several structures used with lighting - 
//We will include a Material structure which controls how much light
//is absorbed/reflected by a surface. And 3 light type structures - 
//directional lights (Eg, the sun. Aka Parallel/Infinite lights), spot lights
//(like a bulb) and spot lights (tourch).
//
//All will match up with the structures defined in LightHelper.fx - by that
//I mean that the strcutres will adhear to HLSL data packing rules. 
//
//Modified 30/09/13: With our tile based forward renderer, we will handle
//spot and point lights together (Ie, in the same buffer). All directional
//lights will be uploaded to each tile based forward shader as they will
//affect every tile anyway. 
//
//Anyway, the TileBasedLight struct below will be used in my TileBasedForwardRenderer.
//
//The idea is to retain as much functionality from my framework as possible. Two reasons, 
//1)Time constrains do not allow me to start from scratch and 2) I intend to use
//this rendering system/engine in my Games Case project. 

#pragma once

struct Material
{
	//Contrcutor - automatically clears memory to 0
	Material()
	{
		ZeroMemory(this, sizeof(this));
		Ambient = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
		Diffuse = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
		Specular = XMFLOAT4(1.0f, 1.0f, 1.0f, 64.0f);
		//Defaults to off. 
		Reflection = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f);
	}

	//Reflection properties - rgba
	XMFLOAT4 Ambient;
	//Diffuse.a == commonly taken as the alpha value returned from the PS
	XMFLOAT4 Diffuse; 
	//Specular.w == shinyness of the surface - aka the Specular Power
	XMFLOAT4 Specular;

	//Used in reflection mapping.
	XMFLOAT4 Reflection;
};

struct DirectionalLight
{
	DirectionalLight()
	{
		ZeroMemory(this, sizeof(this));

		Ambient = XMFLOAT4(0.2f, 0.2f, 0.2f, 1.0f);
		Diffuse = XMFLOAT4(0.3f, 0.3f, 0.3f, 1.0f);
		Specular = XMFLOAT4(0.25f, 0.25f, 0.25f, 1.0f);
	}

	//Colour properties.
	XMFLOAT4 Ambient;
	XMFLOAT4 Diffuse;
	XMFLOAT4 Specular;

	//Directional vector.
	XMFLOAT3 Direction;
	
private:
	//Padding - allows us to easily set an array of lights.
	float Pad;
};

struct PointLight
{
	//Constructor - clears memory
	PointLight()
	{
		ZeroMemory(this, sizeof(this));
	}

	//Colour properties
	XMFLOAT4 Ambient;
	XMFLOAT4 Diffuse;
	XMFLOAT4 Specular;

	//point lights have a location
	XMFLOAT3 Position;
	//We also include a range paramter (world space)
	//if the distance from the light source and the surface point
	//is > range, then the surface point recives NO light from this
	//point light and thus we can return early from the calculation
	//function.
	//
	//Position and Range will be packed in to a 4D vector.
	float Range;

	//Attenutation - essentially weakens the light intensity 
	//as range increases
	XMFLOAT3 Attenuation;
private:
	//Again, need padding.
	float Pad;
};

struct SpotLight
{
	//Constructor clears memory to 0
	SpotLight()
	{
		ZeroMemory(this, sizeof(this));
	}

	//Colour properties
	XMFLOAT4 Ambient;
	XMFLOAT4 Diffuse;
	XMFLOAT4 Specular;

	//Spot lights have a location (world space)
	XMFLOAT3 Position;
	//and a range (like Point Lights)
	float    Range;

	//Direction the Spot light is shining.
	XMFLOAT3 Direction;
	//Spot indicates how wide the spot is
	float    Spot;

	//Attenuation
	XMFLOAT3 Attenuation;
private:
	//And again, padding. (The idea is to have everything packed in 4D vectors)
	float Pad;
};

struct TileBasedLight
{
	//Clears memory to 0.
	TileBasedLight()
	{
		ZeroMemory(this, sizeof(TileBasedLight));
	}

	//Creates point light
	void InitPointLight(XMFLOAT4 amb, XMFLOAT4 diff, XMFLOAT4 spec,
			XMFLOAT3 pos, float range)
	{
		Ambient = amb;
		Diffuse = diff;
		Specular = spec;

		PositionW = pos;
		Range = range;

		//Init spot to -1 indicating that this is a Point light. 
		Spot = -1.0f;
	}

	void InitSpotLight(XMFLOAT4 amb, XMFLOAT4 diff, XMFLOAT4 spec,
			XMFLOAT3 pos, float range,
			XMFLOAT3 dir, float spot)
	{
		Ambient = amb;
		Diffuse = diff;
		Specular = spec;

		PositionW = pos;
		Range = range;

		Direction = dir;
		Spot = spot;
	}

	//Light Colour
	XMFLOAT4 Ambient;
	XMFLOAT4 Diffuse;
	XMFLOAT4 Specular;

	//Light position (world space) - shared by both spot and point lights
	XMFLOAT3 PositionW;
	//Light range
	float    Range;

	//Direction - Spot light only. Note, if the Spot value is -1, then
	//it will be interpreted as a point light
	XMFLOAT3 Direction;
	float Spot;
};